using System;
using System.Web;
using System.Web.Mvc;
using Orchard.DisplayManagement;
using Orchard.DisplayManagement.Shapes;
using Orchard.Localization;
using Orchard.Mvc.Html;
using Orchard.Mvc.Spooling;
using Orchard.Security;
using Orchard.Security.Permissions;
using Orchard.UI.Resources;

namespace Orchard.Mvc
{
    public class ViewUserControl<TModel> : System.Web.Mvc.ViewUserControl<TModel>, IOrchardViewPage
    {
        private ScriptRegister _scriptRegister;
        private ResourceRegister _stylesheetRegister;

        private object _display;
        private object _layout;

        public Localizer T { get; private set; } = NullLocalizer.Instance;
        public dynamic Display => _display;
        public dynamic New => ShapeFactory;
        public dynamic Layout => _layout;
        public WorkContext WorkContext { get; private set; }

        private IDisplayHelperFactory _displayHelperFactory;
        public IDisplayHelperFactory DisplayHelperFactory => _displayHelperFactory ?? (_displayHelperFactory = WorkContext.Resolve<IDisplayHelperFactory>());

        private IShapeFactory _shapeFactory;
        public IShapeFactory ShapeFactory => _shapeFactory ?? (_shapeFactory = WorkContext.Resolve<IShapeFactory>());

        private IAuthorizer _authorizer;
        public IAuthorizer Authorizer => _authorizer ?? (_authorizer = WorkContext.Resolve<IAuthorizer>());

        public ScriptRegister Script
        {
            get
            {
                return _scriptRegister ??
                    (_scriptRegister = new ViewPage.ViewPageScriptRegister(Writer, Html.ViewDataContainer, Html.GetWorkContext().Resolve<IResourceManager>()));
            }
        }

        public ResourceRegister Style
        {
            get
            {
                return _stylesheetRegister ??
                    (_stylesheetRegister = new ResourceRegister(Html.ViewDataContainer, Html.GetWorkContext().Resolve<IResourceManager>(), "stylesheet"));
            }
        }

        public virtual void RegisterLink(LinkEntry link)
        {
            Html.GetWorkContext().Resolve<IResourceManager>().RegisterLink(link);
        }

        public void SetMeta(string name = null, string content = null, string httpEquiv = null, string charset = null)
        {
            var metaEntry = new MetaEntry(name, content, httpEquiv, charset);
            SetMeta(metaEntry);
        }

        public virtual void SetMeta(MetaEntry meta)
        {
            Html.GetWorkContext().Resolve<IResourceManager>().SetMeta(meta);
        }

        public void AppendMeta(string name, string content, string contentSeparator)
        {
            AppendMeta(new MetaEntry { Name = name, Content = content }, contentSeparator);
        }

        public virtual void AppendMeta(MetaEntry meta, string contentSeparator)
        {
            Html.GetWorkContext().Resolve<IResourceManager>().AppendMeta(meta, contentSeparator);
        }

        public override void RenderView(ViewContext viewContext)
        {
            WorkContext = viewContext.GetWorkContext();

            T = LocalizationUtilities.Resolve(viewContext, AppRelativeVirtualPath);
            _display = DisplayHelperFactory.CreateHelper(viewContext, this);
            _layout = WorkContext.Layout;

            base.RenderView(viewContext);
        }

        public MvcHtmlString H(string value)
        {
            return MvcHtmlString.Create(Html.Encode(value));
        }

        public bool AuthorizedFor(Permission permission)
        {
            return Authorizer.Authorize(permission);
        }

        public bool HasText(object thing)
        {
            return !string.IsNullOrWhiteSpace(Convert.ToString(thing));
        }

        public OrchardTagBuilder Tag(dynamic shape, string tagName)
        {
            return Html.GetWorkContext().Resolve<ITagBuilderFactory>().Create(shape, tagName);
        }

        public IHtmlString DisplayChildren(dynamic shape)
        {
            var writer = new HtmlStringWriter();
            foreach (var item in shape)
            {
                writer.Write(Display(item));
            }
            return writer;
        }

        public IDisposable Capture(Action<IHtmlString> callback)
        {
            return new ViewPage.CaptureScope(Writer, callback);
        }

    }

    public class ViewUserControl : ViewUserControl<dynamic>
    {
    }
}
